home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / farsi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-29  |  36.5 KB  |  2,305 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * farsi.c: functions for Farsi language
  11.  *
  12.  * Included by main.c, when FKMAP is defined.
  13.  */
  14.  
  15. static int toF_Xor_X_ __ARGS((int c));
  16. static int F_is_TyE __ARGS((int c));
  17. static int F_is_TyC_TyD __ARGS((int c));
  18. static int F_is_TyB_TyC_TyD __ARGS((int src, int offset));
  19. static int toF_TyB __ARGS((int c));
  20. static void put_curr_and_l_to_X __ARGS((int c));
  21. static void put_and_redo __ARGS((int c));
  22. static void chg_c_toX_orX __ARGS((void));
  23. static void chg_c_to_X_orX_ __ARGS((void));
  24. static void chg_c_to_X_or_X __ARGS((void));
  25. static void chg_l_to_X_orX_ __ARGS((void));
  26. static void chg_l_toXor_X __ARGS((void));
  27. static void chg_r_to_Xor_X_ __ARGS((void));
  28. static int toF_leading __ARGS((int c));
  29. static int toF_Rjoin __ARGS((int c));
  30. static int canF_Ljoin __ARGS((int c));
  31. static int canF_Rjoin __ARGS((int c));
  32. static int F_isterm __ARGS((int c));
  33. static int toF_ending __ARGS((int c));
  34. static void lrswapbuf __ARGS((char_u *buf, int len));
  35.  
  36. /*
  37. ** Convert the given Farsi character into a _X or _X_ type
  38. */
  39.     static int
  40. toF_Xor_X_(c)
  41.     int    c;
  42. {
  43.     int tempc;
  44.  
  45.     switch (c)
  46.     {
  47.     case BE:
  48.         return _BE;
  49.     case PE:
  50.         return _PE;
  51.     case TE:
  52.         return _TE;
  53.     case SE:
  54.         return _SE;
  55.     case JIM:
  56.         return _JIM;
  57.     case CHE:
  58.         return _CHE;
  59.     case HE_J:
  60.         return _HE_J;
  61.     case XE:
  62.         return _XE;
  63.     case SIN:
  64.         return _SIN;
  65.     case SHIN:
  66.         return _SHIN;
  67.     case SAD:
  68.         return _SAD;
  69.     case ZAD:
  70.         return _ZAD;
  71.     case AYN:
  72.         return _AYN;
  73.     case AYN_:
  74.         return _AYN_;
  75.     case GHAYN:
  76.         return _GHAYN;
  77.     case GHAYN_:
  78.         return _GHAYN_;
  79.     case FE:
  80.         return _FE;
  81.     case GHAF:
  82.         return _GHAF;
  83.     case KAF:
  84.         return _KAF;
  85.     case GAF:
  86.         return _GAF;
  87.     case LAM:
  88.         return _LAM;
  89.     case MIM:
  90.         return _MIM;
  91.     case NOON:
  92.         return _NOON;
  93.     case YE:
  94.     case YE_:
  95.         return _YE;
  96.     case YEE:
  97.     case YEE_:
  98.         return _YEE;
  99.     case IE:
  100.     case IE_:
  101.         return _IE;
  102.     case F_HE:
  103.         tempc = _HE;
  104.  
  105.         if (p_ri && (curwin->w_cursor.col+1 < STRLEN(ml_get_curline())))
  106.         {
  107.             inc_cursor();
  108.  
  109.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  110.             tempc = _HE_;
  111.  
  112.             dec_cursor();
  113.         }
  114.         if (!p_ri && STRLEN(ml_get_curline()))
  115.         {
  116.             dec_cursor();
  117.  
  118.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  119.             tempc = _HE_;
  120.  
  121.             inc_cursor();
  122.         }
  123.  
  124.         return tempc;
  125.     }
  126.     return 0;
  127. }
  128.  
  129. /*
  130. ** Convert the given Farsi character into Farsi capital character .
  131. */
  132.     int
  133. toF_TyA(c)
  134.     int    c ;
  135. {
  136.     switch (c)
  137.     {
  138.     case ALEF_:
  139.         return ALEF;
  140.     case ALEF_U_H_:
  141.         return ALEF_U_H;
  142.     case _BE:
  143.         return BE;
  144.     case _PE:
  145.         return PE;
  146.     case _TE:
  147.         return TE;
  148.     case _SE:
  149.         return SE;
  150.     case _JIM:
  151.         return JIM;
  152.     case _CHE:
  153.         return CHE;
  154.     case _HE_J:
  155.         return HE_J;
  156.     case _XE:
  157.         return XE;
  158.     case _SIN:
  159.         return SIN;
  160.     case _SHIN:
  161.         return SHIN;
  162.     case _SAD:
  163.         return SAD;
  164.     case _ZAD:
  165.         return ZAD;
  166.     case _AYN:
  167.     case AYN_:
  168.     case _AYN_:
  169.         return AYN;
  170.     case _GHAYN:
  171.     case GHAYN_:
  172.     case _GHAYN_:
  173.         return GHAYN;
  174.     case _FE:
  175.         return FE;
  176.     case _GHAF:
  177.         return GHAF;
  178. /* I am not sure what it is !!!        case _KAF_H: */
  179.     case _KAF:
  180.         return KAF;
  181.     case _GAF:
  182.         return GAF;
  183.     case _LAM:
  184.         return LAM;
  185.     case _MIM:
  186.         return MIM;
  187.     case _NOON:
  188.         return NOON;
  189.     case _YE:
  190.     case YE_:
  191.         return YE;
  192.     case _YEE:
  193.     case YEE_:
  194.         return YEE;
  195.     case TEE_:
  196.         return TEE;
  197.     case _IE:
  198.     case IE_:
  199.         return IE;
  200.     case _HE:
  201.     case _HE_:
  202.         return F_HE;
  203.     }
  204.     return c;
  205. }
  206.  
  207. /*
  208. ** Is the character under the cursor+offset in the given buffer a join type.
  209. ** That is a character that is combined with the others.
  210. ** Note: the offset is used only for command line buffer.
  211. */
  212.     static int
  213. F_is_TyB_TyC_TyD(src, offset)
  214.     int        src,    offset;
  215. {
  216. int    c;
  217.  
  218.     if ( src == SRC_EDT)
  219.     c = gchar_cursor();
  220.     else
  221.     c = cmd_gchar(AT_CURSOR+offset);
  222.  
  223.     switch (c)
  224.     {
  225.     case _LAM:
  226.     case _BE:
  227.     case _PE:
  228.     case _TE:
  229.     case _SE:
  230.     case _JIM:
  231.     case _CHE:
  232.     case _HE_J:
  233.     case _XE:
  234.     case _SIN:
  235.     case _SHIN:
  236.     case _SAD:
  237.     case _ZAD:
  238.     case _TA:
  239.     case _ZA:
  240.     case _AYN:
  241.     case _AYN_:
  242.     case _GHAYN:
  243.     case _GHAYN_:
  244.     case _FE:
  245.     case _GHAF:
  246.     case _KAF:
  247.     case _KAF_H:
  248.     case _GAF:
  249.     case _MIM:
  250.     case _NOON:
  251.     case _YE:
  252.     case _YEE:
  253.     case _IE:
  254.     case _HE_:
  255.     case _HE:
  256.         return TRUE;
  257.     }
  258.     return FALSE;
  259. }
  260.  
  261. /*
  262. ** Is the Farsi character one of the terminating only type.
  263. */
  264.     static int
  265. F_is_TyE(c)
  266.     int        c;
  267. {
  268.     switch (c)
  269.     {
  270.     case ALEF_A:
  271.     case ALEF_D_H:
  272.     case DAL:
  273.     case ZAL:
  274.     case RE:
  275.     case ZE:
  276.     case JE:
  277.     case WAW:
  278.     case WAW_H:
  279.     case HAMZE:
  280.         return TRUE;
  281.     }
  282.     return FALSE;
  283. }
  284.  
  285. /*
  286. ** Is the Farsi character one of the none leading type.
  287. */
  288.     static int
  289. F_is_TyC_TyD(c)
  290.     int        c;
  291. {
  292.     switch (c)
  293.     {
  294.     case ALEF_:
  295.     case ALEF_U_H_:
  296.     case _AYN_:
  297.     case AYN_:
  298.     case _GHAYN_:
  299.     case GHAYN_:
  300.     case _HE_:
  301.     case YE_:
  302.     case IE_:
  303.     case TEE_:
  304.     case YEE_:
  305.         return TRUE;
  306.     }
  307.     return FALSE;
  308. }
  309.  
  310. /*
  311. ** Convert a none leading Farsi char into a leading type.
  312. */
  313.     static int
  314. toF_TyB(c)
  315.     int        c;
  316. {
  317.     switch (c)
  318.     {
  319.     case ALEF_:    return ALEF;
  320.     case ALEF_U_H_:        return ALEF_U_H;
  321.     case _AYN_:    return _AYN;
  322.     case AYN_:    return AYN;    /* exception - there are many of them */
  323.     case _GHAYN_:    return _GHAYN;
  324.     case GHAYN_:    return GHAYN;    /* exception - there are many of them */
  325.     case _HE_:    return _HE;
  326.     case YE_:    return YE;
  327.     case IE_:    return IE;
  328.     case TEE_:    return TEE;
  329.     case YEE_:    return YEE;
  330.     }
  331.     return c;
  332. }
  333.  
  334. /*
  335. ** Overwrite the current redo and cursor characters + left adjust
  336. */
  337.     static void
  338. put_curr_and_l_to_X(c)
  339.     int          c;
  340. {
  341.     int    tempc;
  342.  
  343.     if (curwin->w_p_rl && p_ri)
  344.     return;
  345.  
  346.     if ( (curwin->w_cursor.col < STRLEN(ml_get_curline())))
  347.     {
  348.     if ((p_ri && curwin->w_cursor.col) || !p_ri)
  349.     {
  350.         if (p_ri)
  351.         dec_cursor();
  352.         else
  353.         inc_cursor();
  354.  
  355.         if (F_is_TyC_TyD((tempc = gchar_cursor())))
  356.         {
  357.         pchar_cursor(toF_TyB(tempc));
  358.         AppendCharToRedobuff(K_BS);
  359.         AppendCharToRedobuff(tempc);
  360.         }
  361.  
  362.         if (p_ri)
  363.         inc_cursor();
  364.         else
  365.         dec_cursor();
  366.     }
  367.     }
  368.  
  369.     put_and_redo(c);
  370. }
  371.  
  372.     static void
  373. put_and_redo(c)
  374.     int c;
  375. {
  376.     pchar_cursor(c);
  377.     AppendCharToRedobuff(K_BS);
  378.     AppendCharToRedobuff(c);
  379. }
  380.  
  381. /*
  382. ** Change the char. under the cursor to a X_ or X type
  383. */
  384.     static void
  385. chg_c_toX_orX()
  386. {
  387.     int    tempc, curc;
  388.  
  389.     switch ((curc = gchar_cursor()))
  390.     {
  391.     case _BE:
  392.         tempc = BE;
  393.         break;
  394.     case _PE:
  395.         tempc = PE;
  396.         break;
  397.     case _TE:
  398.         tempc = TE;
  399.         break;
  400.     case _SE:
  401.         tempc = SE;
  402.         break;
  403.     case _JIM:
  404.         tempc = JIM;
  405.         break;
  406.     case _CHE:
  407.         tempc = CHE;
  408.         break;
  409.     case _HE_J:
  410.         tempc = HE_J;
  411.         break;
  412.     case _XE:
  413.         tempc = XE;
  414.         break;
  415.     case _SIN:
  416.         tempc = SIN;
  417.         break;
  418.     case _SHIN:
  419.         tempc = SHIN;
  420.         break;
  421.     case _SAD:
  422.         tempc = SAD;
  423.         break;
  424.     case _ZAD:
  425.         tempc = ZAD;
  426.         break;
  427.     case _FE:
  428.         tempc = FE;
  429.         break;
  430.     case _GHAF:
  431.         tempc = GHAF;
  432.         break;
  433.     case _KAF_H:
  434.     case _KAF:
  435.         tempc = KAF;
  436.         break;
  437.     case _GAF:
  438.         tempc = GAF;
  439.         break;
  440.     case _AYN:
  441.         tempc = AYN;
  442.         break;
  443.     case _AYN_:
  444.         tempc = AYN_;
  445.         break;
  446.     case _GHAYN:
  447.         tempc = GHAYN;
  448.         break;
  449.     case _GHAYN_:
  450.         tempc = GHAYN_;
  451.         break;
  452.     case _LAM:
  453.         tempc = LAM;
  454.         break;
  455.     case _MIM:
  456.         tempc = MIM;
  457.         break;
  458.     case _NOON:
  459.         tempc = NOON;
  460.         break;
  461.     case _HE:
  462.     case _HE_:
  463.         tempc = F_HE;
  464.         break;
  465.     case _YE:
  466.     case _IE:
  467.     case _YEE:
  468.         if (p_ri)
  469.         {
  470.             inc_cursor();
  471.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  472.                 tempc = (curc == _YE ? YE_ :
  473.                 (curc == _IE ? IE_ : YEE_));
  474.             else
  475.                 tempc = (curc == _YE ? YE :
  476.                 (curc == _IE ? IE : YEE));
  477.             dec_cursor();
  478.         }
  479.         else
  480.         {
  481.             if (curwin->w_cursor.col)
  482.             {
  483.             dec_cursor();
  484.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  485.                 tempc = (curc == _YE ? YE_ :
  486.                 (curc == _IE ? IE_ : YEE_));
  487.             else
  488.                 tempc = (curc == _YE ? YE :
  489.                 (curc == _IE ? IE : YEE));
  490.             inc_cursor();
  491.             }
  492.             else
  493.                 tempc = (curc == _YE ? YE :
  494.                 (curc == _IE ? IE : YEE));
  495.         }
  496.         break;
  497.     default:
  498.         tempc = 0;
  499.     }
  500.  
  501.     if (tempc)
  502.     put_and_redo(tempc);
  503. }
  504.  
  505. /*
  506. ** Change the char. under the cursor to a _X_ or X_ type
  507. */
  508.  
  509.     static void
  510. chg_c_to_X_orX_()
  511. {
  512.     int    tempc;
  513.  
  514.     switch (gchar_cursor())
  515.     {
  516.     case ALEF:
  517.         tempc = ALEF_;
  518.         break;
  519.     case ALEF_U_H:
  520.         tempc = ALEF_U_H_;
  521.         break;
  522.     case _AYN:
  523.         tempc = _AYN_;
  524.         break;
  525.     case AYN:
  526.         tempc = AYN_;
  527.         break;
  528.     case _GHAYN:
  529.         tempc = _GHAYN_;
  530.         break;
  531.     case GHAYN:
  532.         tempc = GHAYN_;
  533.         break;
  534.     case _HE:
  535.         tempc = _HE_;
  536.         break;
  537.     case YE:
  538.         tempc = YE_;
  539.         break;
  540.     case IE:
  541.         tempc = IE_;
  542.         break;
  543.     case TEE:
  544.         tempc = TEE_;
  545.         break;
  546.     case YEE:
  547.         tempc = YEE_;
  548.         break;
  549.     default:
  550.         tempc = 0;
  551.     }
  552.  
  553.     if (tempc)
  554.     put_and_redo(tempc);
  555. }
  556.  
  557. /*
  558. ** Change the char. under the cursor to a _X_ or _X type
  559. */
  560.     static void
  561. chg_c_to_X_or_X ()
  562. {
  563.     int    tempc;
  564.  
  565.     tempc = gchar_cursor();
  566.  
  567.     if (curwin->w_cursor.col+1 < STRLEN(ml_get_curline()))
  568.     {
  569.     inc_cursor();
  570.  
  571.     if ((tempc == F_HE) && (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR)))
  572.     {
  573.         tempc = _HE_;
  574.  
  575.         dec_cursor();
  576.  
  577.         put_and_redo(tempc);
  578.         return;
  579.     }
  580.  
  581.     dec_cursor();
  582.     }
  583.  
  584.     if ((tempc = toF_Xor_X_(tempc)))
  585.     put_and_redo(tempc);
  586. }
  587.  
  588. /*
  589. ** Change the character left to the cursor to a _X_ or X_ type
  590. */
  591.     static void
  592. chg_l_to_X_orX_ ()
  593. {
  594.     int    tempc;
  595.  
  596.     if (!curwin->w_cursor.col &&
  597.     (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  598.     return;
  599.  
  600.     if (!curwin->w_cursor.col && p_ri)
  601.     return;
  602.  
  603.     if (p_ri)
  604.     dec_cursor();
  605.     else
  606.     inc_cursor();
  607.  
  608.     switch (gchar_cursor())
  609.     {
  610.     case ALEF:
  611.         tempc = ALEF_;
  612.         break;
  613.     case ALEF_U_H:
  614.         tempc = ALEF_U_H_;
  615.         break;
  616.     case _AYN:
  617.         tempc = _AYN_;
  618.         break;
  619.     case AYN:
  620.         tempc = AYN_;
  621.         break;
  622.     case _GHAYN:
  623.         tempc = _GHAYN_;
  624.         break;
  625.     case GHAYN:
  626.         tempc = GHAYN_;
  627.         break;
  628.     case _HE:
  629.         tempc = _HE_;
  630.         break;
  631.     case YE:
  632.         tempc = YE_;
  633.         break;
  634.     case IE:
  635.         tempc = IE_;
  636.         break;
  637.     case TEE:
  638.         tempc = TEE_;
  639.         break;
  640.     case YEE:
  641.         tempc = YEE_;
  642.         break;
  643.     default:
  644.         tempc = 0;
  645.     }
  646.  
  647.     if (tempc)
  648.     put_and_redo(tempc);
  649.  
  650.     if (p_ri)
  651.     inc_cursor();
  652.     else
  653.     dec_cursor();
  654. }
  655.  
  656. /*
  657. ** Change the charcter left to the cursor to a X or _X type
  658. */
  659.  
  660.     static void
  661. chg_l_toXor_X ()
  662. {
  663.     int    tempc;
  664.  
  665.     if (!curwin->w_cursor.col &&
  666.     (curwin->w_cursor.col+1 == STRLEN(ml_get_curline())))
  667.     return;
  668.  
  669.     if (!curwin->w_cursor.col && p_ri)
  670.     return;
  671.  
  672.     if (p_ri)
  673.     dec_cursor();
  674.     else
  675.     inc_cursor();
  676.  
  677.     switch (gchar_cursor())
  678.     {
  679.     case ALEF_:
  680.         tempc = ALEF;
  681.         break;
  682.     case ALEF_U_H_:
  683.         tempc = ALEF_U_H;
  684.         break;
  685.     case _AYN_:
  686.         tempc = _AYN;
  687.         break;
  688.     case AYN_:
  689.         tempc = AYN;
  690.         break;
  691.     case _GHAYN_:
  692.         tempc = _GHAYN;
  693.         break;
  694.     case GHAYN_:
  695.         tempc = GHAYN;
  696.         break;
  697.     case _HE_:
  698.         tempc = _HE;
  699.         break;
  700.     case YE_:
  701.         tempc = YE;
  702.         break;
  703.     case IE_:
  704.         tempc = IE;
  705.         break;
  706.     case TEE_:
  707.         tempc = TEE;
  708.         break;
  709.     case YEE_:
  710.         tempc = YEE;
  711.         break;
  712.     default:
  713.         tempc = 0;
  714.     }
  715.  
  716.     if (tempc)
  717.     put_and_redo(tempc);
  718.  
  719.     if (p_ri)
  720.     inc_cursor();
  721.     else
  722.     dec_cursor();
  723. }
  724.  
  725. /*
  726. ** Change the charcter right to the cursor to a _X or _X_ type
  727. */
  728.  
  729.     static void
  730. chg_r_to_Xor_X_()
  731. {
  732. int tempc, c;
  733.  
  734.     if (curwin->w_cursor.col)
  735.     {
  736.     if (!p_ri)
  737.         dec_cursor();
  738.  
  739.     tempc = gchar_cursor();
  740.  
  741.     if ((c = toF_Xor_X_(tempc)))
  742.         put_and_redo(c);
  743.  
  744.     if (!p_ri)
  745.         inc_cursor();
  746.  
  747.     }
  748. }
  749.  
  750. /*
  751. ** Map Farsi keyboard when in fkmap mode.
  752. */
  753.  
  754.     int
  755. fkmap(c)
  756.     int c;
  757. {
  758.     int        tempc;
  759.     static int    revins;
  760.  
  761.     if (vim_isdigit(c) || ((c == '.' || c == '+' || c == '-' ||
  762.     c == '^' || c == '%' || c == '#' || c == '=')  && revins))
  763.     {
  764.     if (!revins)
  765.     {
  766.         if (curwin->w_cursor.col)
  767.         {
  768.         if (!p_ri)
  769.             dec_cursor();
  770.  
  771.             chg_c_toX_orX ();
  772.             chg_l_toXor_X ();
  773.  
  774.         if (!p_ri)
  775.             inc_cursor();
  776.         }
  777.     }
  778.  
  779.     arrow_used = TRUE;
  780.     stop_arrow();
  781.  
  782.     if (!curwin->w_p_rl && revins)
  783.         inc_cursor();
  784.  
  785.     ++revins;
  786.     p_ri=1;
  787.     }
  788.     else
  789.     {
  790.     if (revins)
  791.     {
  792.         arrow_used = TRUE;
  793.         stop_arrow();
  794.  
  795.         revins=0;
  796.         tempc = gchar_cursor();
  797.         if (curwin->w_p_rl)
  798.         {
  799.         while ((F_isdigit(gchar_cursor())
  800.                 || (gchar_cursor() == F_PERIOD
  801.                 || gchar_cursor() == F_PLUS
  802.                 || gchar_cursor() == F_MINUS
  803.                 || gchar_cursor() == F_MUL
  804.                 || gchar_cursor() == F_DIVIDE
  805.                 || gchar_cursor() == F_PERCENT
  806.                 || gchar_cursor() == F_EQUALS))
  807.             && gchar_cursor()!= NUL)
  808.             ++curwin->w_cursor.col;
  809.         }
  810.         else
  811.         {
  812.         if (curwin->w_cursor.col)
  813.             while ((F_isdigit(gchar_cursor())
  814.                 || (gchar_cursor() == F_PERIOD
  815.                 || gchar_cursor() == F_PLUS
  816.                 || gchar_cursor() == F_MINUS
  817.                 || gchar_cursor() == F_MUL
  818.                 || gchar_cursor() == F_DIVIDE
  819.                 || gchar_cursor() == F_PERCENT
  820.                 || gchar_cursor() == F_EQUALS))
  821.                 && --curwin->w_cursor.col);
  822.  
  823.         if (!F_isdigit(gchar_cursor()))
  824.             ++curwin->w_cursor.col;
  825.         }
  826.     }
  827.     }
  828.  
  829.     if (!revins)
  830.     {
  831.     if (curwin->w_p_rl)
  832.         p_ri=0;
  833.     if (!curwin->w_p_rl)
  834.         p_ri=1;
  835.     }
  836.  
  837.     if ((c < 0x100) && (isalpha(c) || c == '&' ||   c == '^' ||    c == ';' ||
  838.                 c == '\''||    c == ',' || c == '[' ||
  839.                 c == ']' ||    c == '{' || c == '}'    ))
  840.     chg_r_to_Xor_X_();
  841.  
  842.     tempc = 0;
  843.  
  844.     switch (c)
  845.     {
  846.     case '`':
  847.     case ' ':
  848.     case '.':
  849.     case '!':
  850.     case '"':
  851.     case '$':
  852.     case '%':
  853.     case '^':
  854.     case '&':
  855.     case '/':
  856.     case '(':
  857.     case ')':
  858.     case '=':
  859.     case '\\':
  860.     case '?':
  861.     case '+':
  862.     case '-':
  863.     case '_':
  864.     case '*':
  865.     case ':':
  866.     case '#':
  867.     case '~':
  868.     case '@':
  869.     case '<':
  870.     case '>':
  871.     case '{':
  872.     case '}':
  873.     case '|':
  874.     case '0':
  875.     case '1':
  876.     case '2':
  877.     case '3':
  878.     case '4':
  879.     case '5':
  880.     case '6':
  881.     case '7':
  882.     case '8':
  883.     case '9':
  884.     case 'B':
  885.     case 'E':
  886.     case 'F':
  887.     case 'H':
  888.     case 'I':
  889.     case 'K':
  890.     case 'L':
  891.     case 'M':
  892.     case 'O':
  893.     case 'P':
  894.     case 'Q':
  895.     case 'R':
  896.     case 'T':
  897.     case 'U':
  898.     case 'W':
  899.     case 'Y':
  900.     case  NL:
  901.     case  TAB:
  902.  
  903.         if (p_ri && c == NL && curwin->w_cursor.col)
  904.         {
  905.         /*
  906.         ** If the char before the cursor is _X_ or X_ do not change
  907.         ** the one under the cursor with X type.
  908.         */
  909.  
  910.         dec_cursor();
  911.  
  912.         if (F_isalpha(gchar_cursor()))
  913.         {
  914.             inc_cursor();
  915.             return NL;
  916.         }
  917.  
  918.         inc_cursor();
  919.         }
  920.  
  921.         if (!p_ri)
  922.         if (!curwin->w_cursor.col)
  923.         {
  924.         switch (c)
  925.         {
  926.             case '0':    return FARSI_0;
  927.             case '1':    return FARSI_1;
  928.             case '2':    return FARSI_2;
  929.             case '3':    return FARSI_3;
  930.             case '4':    return FARSI_4;
  931.             case '5':    return FARSI_5;
  932.             case '6':    return FARSI_6;
  933.             case '7':    return FARSI_7;
  934.             case '8':    return FARSI_8;
  935.             case '9':    return FARSI_9;
  936.             case 'B':    return F_PSP;
  937.             case 'E':    return JAZR_N;
  938.             case 'F':    return ALEF_D_H;
  939.             case 'H':    return ALEF_A;
  940.             case 'I':    return TASH;
  941.             case 'K':    return F_LQUOT;
  942.             case 'L':    return F_RQUOT;
  943.             case 'M':    return HAMZE;
  944.             case 'O':    return '[';
  945.             case 'P':    return ']';
  946.             case 'Q':    return OO;
  947.             case 'R':    return MAD_N;
  948.             case 'T':    return OW;
  949.             case 'U':    return MAD;
  950.             case 'W':    return OW_OW;
  951.             case 'Y':    return JAZR;
  952.             case '`':    return F_PCN;
  953.             case '!':    return F_EXCL;
  954.             case '@':    return F_COMMA;
  955.             case '#':    return F_DIVIDE;
  956.             case '$':    return F_CURRENCY;
  957.             case '%':    return F_PERCENT;
  958.             case '^':    return F_MUL;
  959.             case '&':    return F_BCOMMA;
  960.             case '*':    return F_STAR;
  961.             case '(':    return F_LPARENT;
  962.             case ')':    return F_RPARENT;
  963.             case '-':    return F_MINUS;
  964.             case '_':    return F_UNDERLINE;
  965.             case '=':    return F_EQUALS;
  966.             case '+':    return F_PLUS;
  967.             case '\\':    return F_BSLASH;
  968.             case '|':    return F_PIPE;
  969.             case ':':    return F_DCOLON;
  970.             case '"':    return F_SEMICOLON;
  971.             case '.':    return F_PERIOD;
  972.             case '/':    return F_SLASH;
  973.             case '<':    return F_LESS;
  974.             case '>':    return F_GREATER;
  975.             case '?':    return F_QUESTION;
  976.             case ' ':    return F_BLANK;
  977.         }
  978.         break;
  979.         }
  980.         if (!p_ri)
  981.         dec_cursor();
  982.  
  983.         switch ((tempc = gchar_cursor()))
  984.         {
  985.         case _BE:
  986.         case _PE:
  987.         case _TE:
  988.         case _SE:
  989.         case _JIM:
  990.         case _CHE:
  991.         case _HE_J:
  992.         case _XE:
  993.         case _SIN:
  994.         case _SHIN:
  995.         case _SAD:
  996.         case _ZAD:
  997.         case _FE:
  998.         case _GHAF:
  999.         case _KAF:
  1000.         case _KAF_H:
  1001.         case _GAF:
  1002.         case _LAM:
  1003.         case _MIM:
  1004.         case _NOON:
  1005.         case _HE:
  1006.         case _HE_:
  1007.         case _TA:
  1008.         case _ZA:
  1009.             put_curr_and_l_to_X(toF_TyA(tempc));
  1010.             break;
  1011.         case _AYN:
  1012.         case _AYN_:
  1013.  
  1014.             if (!p_ri)
  1015.                 if (!curwin->w_cursor.col)
  1016.                 {
  1017.                 put_curr_and_l_to_X(AYN);
  1018.                 break;
  1019.                 }
  1020.  
  1021.             if (p_ri)
  1022.                 inc_cursor();
  1023.             else
  1024.                 dec_cursor();
  1025.  
  1026.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1027.                 tempc = AYN_;
  1028.             else
  1029.                 tempc = AYN;
  1030.  
  1031.             if (p_ri)
  1032.                 dec_cursor();
  1033.             else
  1034.                 inc_cursor();
  1035.  
  1036.             put_curr_and_l_to_X(tempc);
  1037.  
  1038.             break;
  1039.         case _GHAYN:
  1040.         case _GHAYN_:
  1041.  
  1042.             if (!p_ri)
  1043.                 if (!curwin->w_cursor.col)
  1044.                 {
  1045.                 put_curr_and_l_to_X(GHAYN);
  1046.                 break;
  1047.                 }
  1048.  
  1049.             if (p_ri)
  1050.                 inc_cursor();
  1051.             else
  1052.                 dec_cursor();
  1053.  
  1054.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1055.                 tempc = GHAYN_;
  1056.             else
  1057.                 tempc = GHAYN;
  1058.  
  1059.             if (p_ri)
  1060.                 dec_cursor();
  1061.             else
  1062.                 inc_cursor();
  1063.  
  1064.             put_curr_and_l_to_X(tempc);
  1065.             break;
  1066.         case _YE:
  1067.         case _IE:
  1068.         case _YEE:
  1069.             if (!p_ri)
  1070.                 if (!curwin->w_cursor.col)
  1071.                 {
  1072.                 put_curr_and_l_to_X((tempc == _YE ? YE :
  1073.                         (tempc == _IE ? IE : YEE)));
  1074.                 break;
  1075.                 }
  1076.  
  1077.             if (p_ri)
  1078.                 inc_cursor();
  1079.             else
  1080.                 dec_cursor();
  1081.  
  1082.             if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1083.                 tempc = (tempc == _YE ? YE_ :
  1084.                     (tempc == _IE ? IE_ : YEE_));
  1085.             else
  1086.                 tempc = (tempc == _YE ? YE :
  1087.                     (tempc == _IE ? IE : YEE));
  1088.  
  1089.             if (p_ri)
  1090.                 dec_cursor();
  1091.             else
  1092.                 inc_cursor();
  1093.  
  1094.             put_curr_and_l_to_X(tempc);
  1095.             break;
  1096.         }
  1097.  
  1098.         if (!p_ri)
  1099.             inc_cursor();
  1100.  
  1101.         tempc = 0;
  1102.  
  1103.         switch (c)
  1104.         {
  1105.             case '0':    return FARSI_0;
  1106.             case '1':    return FARSI_1;
  1107.             case '2':    return FARSI_2;
  1108.             case '3':    return FARSI_3;
  1109.             case '4':    return FARSI_4;
  1110.             case '5':    return FARSI_5;
  1111.             case '6':    return FARSI_6;
  1112.             case '7':    return FARSI_7;
  1113.             case '8':    return FARSI_8;
  1114.             case '9':    return FARSI_9;
  1115.             case 'B':    return F_PSP;
  1116.             case 'E':    return JAZR_N;
  1117.             case 'F':    return ALEF_D_H;
  1118.             case 'H':    return ALEF_A;
  1119.             case 'I':    return TASH;
  1120.             case 'K':    return F_LQUOT;
  1121.             case 'L':    return F_RQUOT;
  1122.             case 'M':    return HAMZE;
  1123.             case 'O':    return '[';
  1124.             case 'P':    return ']';
  1125.             case 'Q':    return OO;
  1126.             case 'R':    return MAD_N;
  1127.             case 'T':    return OW;
  1128.             case 'U':    return MAD;
  1129.             case 'W':    return OW_OW;
  1130.             case 'Y':    return JAZR;
  1131.             case '`':    return F_PCN;
  1132.             case '!':    return F_EXCL;
  1133.             case '@':    return F_COMMA;
  1134.             case '#':    return F_DIVIDE;
  1135.             case '$':    return F_CURRENCY;
  1136.             case '%':    return F_PERCENT;
  1137.             case '^':    return F_MUL;
  1138.             case '&':    return F_BCOMMA;
  1139.             case '*':    return F_STAR;
  1140.             case '(':    return F_LPARENT;
  1141.             case ')':    return F_RPARENT;
  1142.             case '-':    return F_MINUS;
  1143.             case '_':    return F_UNDERLINE;
  1144.             case '=':    return F_EQUALS;
  1145.             case '+':    return F_PLUS;
  1146.             case '\\':    return F_BSLASH;
  1147.             case '|':    return F_PIPE;
  1148.             case ':':    return F_DCOLON;
  1149.             case '"':    return F_SEMICOLON;
  1150.             case '.':    return F_PERIOD;
  1151.             case '/':    return F_SLASH;
  1152.             case '<':    return F_LESS;
  1153.             case '>':    return F_GREATER;
  1154.             case '?':    return F_QUESTION;
  1155.             case ' ':    return F_BLANK;
  1156.         }
  1157.         break;
  1158.  
  1159.     case 'a':
  1160.         tempc = _SHIN;
  1161.         break;
  1162.     case 'A':
  1163.         tempc = WAW_H;
  1164.         break;
  1165.     case 'b':
  1166.         tempc = ZAL;
  1167.         break;
  1168.     case 'c':
  1169.         tempc = ZE;
  1170.         break;
  1171.     case 'C':
  1172.         tempc = JE;
  1173.         break;
  1174.     case 'd':
  1175.         tempc = _YE;
  1176.         break;
  1177.     case 'D':
  1178.         tempc = _YEE;
  1179.         break;
  1180.     case 'e':
  1181.         tempc = _SE;
  1182.         break;
  1183.     case 'f':
  1184.         tempc = _BE;
  1185.         break;
  1186.     case 'g':
  1187.         tempc = _LAM;
  1188.         break;
  1189.     case 'G':
  1190.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1191.         {
  1192.  
  1193.         if (gchar_cursor() == _LAM)
  1194.             chg_c_toX_orX ();
  1195.         else
  1196.             if (p_ri)
  1197.             chg_c_to_X_or_X ();
  1198.         }
  1199.  
  1200.         if (!p_ri)
  1201.         if (!curwin->w_cursor.col)
  1202.             return ALEF_U_H;
  1203.  
  1204.         if (!p_ri)
  1205.         dec_cursor();
  1206.  
  1207.         if (gchar_cursor() == _LAM)
  1208.         {
  1209.         chg_c_toX_orX ();
  1210.         chg_l_toXor_X ();
  1211.             tempc = ALEF_U_H;
  1212.         }
  1213.         else
  1214.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1215.         {
  1216.             tempc = ALEF_U_H_;
  1217.             chg_l_toXor_X ();
  1218.         }
  1219.         else
  1220.             tempc = ALEF_U_H;
  1221.  
  1222.         if (!p_ri)
  1223.         inc_cursor();
  1224.  
  1225.         return tempc;
  1226.     case 'h':
  1227.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1228.         {
  1229.         if (p_ri)
  1230.             chg_c_to_X_or_X ();
  1231.  
  1232.         }
  1233.  
  1234.         if (!p_ri)
  1235.         if (!curwin->w_cursor.col)
  1236.             return ALEF;
  1237.  
  1238.         if (!p_ri)
  1239.         dec_cursor();
  1240.  
  1241.         if (gchar_cursor() == _LAM)
  1242.         {
  1243.         chg_l_toXor_X();
  1244.         del_char(FALSE);
  1245.         AppendCharToRedobuff(K_BS);
  1246.  
  1247.         if (!p_ri)
  1248.             dec_cursor();
  1249.  
  1250.             tempc = LA;
  1251.         }
  1252.         else
  1253.         {
  1254.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1255.         {
  1256.             tempc = ALEF_;
  1257.             chg_l_toXor_X ();
  1258.         }
  1259.         else
  1260.             tempc = ALEF;
  1261.         }
  1262.  
  1263.         if (!p_ri)
  1264.         inc_cursor();
  1265.  
  1266.         return tempc;
  1267.     case 'i':
  1268.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1269.         {
  1270.         if (!p_ri && !F_is_TyE(tempc))
  1271.             chg_c_to_X_orX_ ();
  1272.         if (p_ri)
  1273.             chg_c_to_X_or_X ();
  1274.  
  1275.         }
  1276.  
  1277.         if (!p_ri && !curwin->w_cursor.col)
  1278.         return _HE;
  1279.  
  1280.         if (!p_ri)
  1281.         dec_cursor();
  1282.  
  1283.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1284.             tempc = _HE_;
  1285.         else
  1286.             tempc = _HE;
  1287.  
  1288.         if (!p_ri)
  1289.         inc_cursor();
  1290.         break;
  1291.     case 'j':
  1292.         tempc = _TE;
  1293.         break;
  1294.     case 'J':
  1295.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1296.         {
  1297.         if (p_ri)
  1298.             chg_c_to_X_or_X ();
  1299.  
  1300.         }
  1301.  
  1302.         if (!p_ri)
  1303.         if (!curwin->w_cursor.col)
  1304.             return TEE;
  1305.  
  1306.         if (!p_ri)
  1307.         dec_cursor();
  1308.  
  1309.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1310.         {
  1311.             tempc = TEE_;
  1312.         chg_l_toXor_X ();
  1313.         }
  1314.         else
  1315.             tempc = TEE;
  1316.  
  1317.         if (!p_ri)
  1318.         inc_cursor();
  1319.  
  1320.         return tempc;
  1321.     case 'k':
  1322.         tempc = _NOON;
  1323.         break;
  1324.     case 'l':
  1325.         tempc = _MIM;
  1326.         break;
  1327.     case 'm':
  1328.         tempc = _PE;
  1329.         break;
  1330.     case 'n':
  1331.     case 'N':
  1332.         tempc = DAL;
  1333.         break;
  1334.     case 'o':
  1335.         tempc = _XE;
  1336.         break;
  1337.     case 'p':
  1338.         tempc = _HE_J;
  1339.         break;
  1340.     case 'q':
  1341.         tempc = _ZAD;
  1342.         break;
  1343.     case 'r':
  1344.         tempc = _GHAF;
  1345.         break;
  1346.     case 's':
  1347.         tempc = _SIN;
  1348.         break;
  1349.     case 'S':
  1350.         tempc = _IE;
  1351.         break;
  1352.     case 't':
  1353.         tempc = _FE;
  1354.         break;
  1355.     case 'u':
  1356.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1357.         {
  1358.             if (!p_ri && !F_is_TyE(tempc))
  1359.             chg_c_to_X_orX_ ();
  1360.             if (p_ri)
  1361.             chg_c_to_X_or_X ();
  1362.  
  1363.         }
  1364.  
  1365.         if (!p_ri && !curwin->w_cursor.col)
  1366.             return _AYN;
  1367.  
  1368.         if (!p_ri)
  1369.             dec_cursor();
  1370.  
  1371.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1372.             tempc = _AYN_;
  1373.         else
  1374.             tempc = _AYN;
  1375.  
  1376.         if (!p_ri)
  1377.             inc_cursor();
  1378.         break;
  1379.     case 'v':
  1380.     case 'V':
  1381.         tempc = RE;
  1382.         break;
  1383.     case 'w':
  1384.         tempc = _SAD;
  1385.         break;
  1386.     case 'x':
  1387.     case 'X':
  1388.         tempc = _TA;
  1389.         break;
  1390.     case 'y':
  1391.         if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1392.         {
  1393.         if (!p_ri && !F_is_TyE(tempc))
  1394.             chg_c_to_X_orX_ ();
  1395.         if (p_ri)
  1396.             chg_c_to_X_or_X ();
  1397.  
  1398.         }
  1399.  
  1400.         if (!p_ri && !curwin->w_cursor.col)
  1401.         return _GHAYN;
  1402.  
  1403.         if (!p_ri)
  1404.         dec_cursor();
  1405.  
  1406.         if (F_is_TyB_TyC_TyD(SRC_EDT, AT_CURSOR))
  1407.         tempc = _GHAYN_;
  1408.         else
  1409.         tempc = _GHAYN;
  1410.  
  1411.         if (!p_ri)
  1412.         inc_cursor();
  1413.  
  1414.         break;
  1415.     case 'z':
  1416.         tempc = _ZA;
  1417.         break;
  1418.     case 'Z':
  1419.         tempc = _KAF_H;
  1420.         break;
  1421.     case ';':
  1422.         tempc = _KAF;
  1423.         break;
  1424.     case '\'':
  1425.         tempc = _GAF;
  1426.         break;
  1427.     case ',':
  1428.         tempc = WAW;
  1429.         break;
  1430.     case '[':
  1431.         tempc = _JIM;
  1432.         break;
  1433.     case ']':
  1434.         tempc = _CHE;
  1435.         break;
  1436.     }
  1437.  
  1438.     if ((F_isalpha(tempc) || F_isdigit(tempc)))
  1439.     {
  1440.     if (!curwin->w_cursor.col  &&  STRLEN(ml_get_curline()))
  1441.         {
  1442.         if (!p_ri && !F_is_TyE(tempc))
  1443.         chg_c_to_X_orX_ ();
  1444.         if (p_ri)
  1445.         chg_c_to_X_or_X ();
  1446.     }
  1447.  
  1448.     if (curwin->w_cursor.col)
  1449.     {
  1450.         if (!p_ri)
  1451.         dec_cursor();
  1452.  
  1453.         if (F_is_TyE(tempc))
  1454.         chg_l_toXor_X ();
  1455.         else
  1456.         chg_l_to_X_orX_ ();
  1457.  
  1458.         if (!p_ri)
  1459.         inc_cursor();
  1460.     }
  1461.     }
  1462.     if (tempc)
  1463.     return tempc;
  1464.     return c;
  1465. }
  1466.  
  1467. /*
  1468. ** Convert a none leading Farsi char into a leading type.
  1469. */
  1470.     static int
  1471. toF_leading(c)
  1472.     int        c;
  1473. {
  1474.     switch (c)
  1475.     {
  1476.     case ALEF_:    return ALEF;
  1477.     case ALEF_U_H_:        return ALEF_U_H;
  1478.     case BE:    return _BE;
  1479.     case PE:    return _PE;
  1480.     case TE:    return _TE;
  1481.     case SE:    return _SE;
  1482.     case JIM:   return _JIM;
  1483.     case CHE:   return _CHE;
  1484.     case HE_J:  return _HE_J;
  1485.     case XE:    return _XE;
  1486.     case SIN:   return _SIN;
  1487.     case SHIN:  return _SHIN;
  1488.     case SAD:   return _SAD;
  1489.     case ZAD:   return _ZAD;
  1490.  
  1491.     case AYN:
  1492.     case AYN_:
  1493.     case _AYN_: return _AYN;
  1494.  
  1495.     case GHAYN:
  1496.     case GHAYN_:
  1497.     case _GHAYN_:    return _GHAYN;
  1498.  
  1499.     case FE:    return _FE;
  1500.     case GHAF:  return _GHAF;
  1501.     case KAF:   return _KAF;
  1502.     case GAF:   return _GAF;
  1503.     case LAM:   return _LAM;
  1504.     case MIM:   return _MIM;
  1505.     case NOON:  return _NOON;
  1506.  
  1507.     case _HE_:
  1508.     case F_HE:    return _HE;
  1509.  
  1510.     case YE:
  1511.     case YE_:    return _YE;
  1512.  
  1513.     case IE_:
  1514.     case IE:    return _IE;
  1515.  
  1516.     case YEE:
  1517.     case YEE_:    return _YEE;
  1518.     }
  1519.     return c;
  1520. }
  1521.  
  1522. /*
  1523. ** Convert a given Farsi char into right joining type.
  1524. */
  1525.     static int
  1526. toF_Rjoin(c)
  1527.     int        c;
  1528. {
  1529.     switch (c)
  1530.     {
  1531.     case ALEF:  return ALEF_;
  1532.     case ALEF_U_H:    return ALEF_U_H_;
  1533.     case BE:    return _BE;
  1534.     case PE:    return _PE;
  1535.     case TE:    return _TE;
  1536.     case SE:    return _SE;
  1537.     case JIM:   return _JIM;
  1538.     case CHE:   return _CHE;
  1539.     case HE_J:  return _HE_J;
  1540.     case XE:    return _XE;
  1541.     case SIN:   return _SIN;
  1542.     case SHIN:  return _SHIN;
  1543.     case SAD:   return _SAD;
  1544.     case ZAD:   return _ZAD;
  1545.  
  1546.     case AYN:
  1547.     case AYN_:
  1548.     case _AYN:  return _AYN_;
  1549.  
  1550.     case GHAYN:
  1551.     case GHAYN_:
  1552.     case _GHAYN_:    return _GHAYN_;
  1553.  
  1554.     case FE:    return _FE;
  1555.     case GHAF:  return _GHAF;
  1556.     case KAF:   return _KAF;
  1557.     case GAF:   return _GAF;
  1558.     case LAM:   return _LAM;
  1559.     case MIM:   return _MIM;
  1560.     case NOON:  return _NOON;
  1561.  
  1562.     case _HE:
  1563.     case F_HE:    return _HE_;
  1564.  
  1565.     case YE:
  1566.     case YE_:    return _YE;
  1567.  
  1568.     case IE_:
  1569.     case IE:    return _IE;
  1570.  
  1571.     case TEE:    return TEE_;
  1572.  
  1573.     case YEE:
  1574.     case YEE_:    return _YEE;
  1575.     }
  1576.     return c;
  1577. }
  1578.  
  1579. /*
  1580. ** Can a given Farsi character join via its left edj.
  1581. */
  1582.     static int
  1583. canF_Ljoin(c)
  1584.     int    c;
  1585. {
  1586.     switch (c)
  1587.     {
  1588.     case _BE:
  1589.     case BE:
  1590.     case PE:
  1591.     case _PE:
  1592.     case TE:
  1593.     case _TE:
  1594.     case SE:
  1595.     case _SE:
  1596.     case JIM:
  1597.     case _JIM:
  1598.     case CHE:
  1599.     case _CHE:
  1600.     case HE_J:
  1601.     case _HE_J:
  1602.     case XE:
  1603.     case _XE:
  1604.     case SIN:
  1605.     case _SIN:
  1606.     case SHIN:
  1607.     case _SHIN:
  1608.     case SAD:
  1609.     case _SAD:
  1610.     case ZAD:
  1611.     case _ZAD:
  1612.     case _TA:
  1613.     case _ZA:
  1614.     case AYN:
  1615.     case _AYN:
  1616.     case _AYN_:
  1617.     case AYN_:
  1618.     case GHAYN:
  1619.     case GHAYN_:
  1620.     case _GHAYN_:
  1621.     case _GHAYN:
  1622.     case FE:
  1623.     case _FE:
  1624.     case GHAF:
  1625.     case _GHAF:
  1626.     case _KAF_H:
  1627.     case KAF:
  1628.     case _KAF:
  1629.     case GAF:
  1630.     case _GAF:
  1631.     case LAM:
  1632.     case _LAM:
  1633.     case MIM:
  1634.     case _MIM:
  1635.     case NOON:
  1636.     case _NOON:
  1637.     case IE:
  1638.     case _IE:
  1639.     case IE_:
  1640.     case YE:
  1641.     case _YE:
  1642.     case YE_:
  1643.     case YEE:
  1644.     case _YEE:
  1645.     case YEE_:
  1646.     case F_HE:
  1647.     case _HE:
  1648.     case _HE_:
  1649.         return TRUE;
  1650.     }
  1651.     return FALSE;
  1652. }
  1653.  
  1654. /*
  1655. ** Can a given Farsi character join via its right edj.
  1656. */
  1657.     static int
  1658. canF_Rjoin(c)
  1659.     int        c;
  1660. {
  1661.     switch (c)
  1662.     {
  1663.     case ALEF:
  1664.     case ALEF_:
  1665.     case ALEF_U_H:
  1666.     case ALEF_U_H_:
  1667.     case DAL:
  1668.     case ZAL:
  1669.     case RE:
  1670.     case JE:
  1671.     case ZE:
  1672.     case TEE:
  1673.     case TEE_:
  1674.     case WAW:
  1675.     case WAW_H:
  1676.         return TRUE;
  1677.     }
  1678.  
  1679.     return canF_Ljoin(c);
  1680.  
  1681. }
  1682.  
  1683. /*
  1684. ** is a given Farsi character a terminating type.
  1685. */
  1686.     static int
  1687. F_isterm(c)
  1688.     int        c;
  1689. {
  1690.     switch (c)
  1691.     {
  1692.     case ALEF:
  1693.     case ALEF_:
  1694.     case ALEF_U_H:
  1695.     case ALEF_U_H_:
  1696.     case DAL:
  1697.     case ZAL:
  1698.     case RE:
  1699.     case JE:
  1700.     case ZE:
  1701.     case WAW:
  1702.     case WAW_H:
  1703.     case TEE:
  1704.     case TEE_:
  1705.         return TRUE;
  1706.     }
  1707.  
  1708.     return FALSE;
  1709. }
  1710.  
  1711. /*
  1712. ** Convert the given Farsi character into a ending type .
  1713. */
  1714.     static int
  1715. toF_ending(c)
  1716.     int        c;
  1717. {
  1718.  
  1719.     switch (c)
  1720.     {
  1721.     case _BE:
  1722.         return BE;
  1723.     case _PE:
  1724.         return PE;
  1725.     case _TE:
  1726.         return TE;
  1727.     case _SE:
  1728.         return SE;
  1729.     case _JIM:
  1730.         return JIM;
  1731.     case _CHE:
  1732.         return CHE;
  1733.     case _HE_J:
  1734.         return HE_J;
  1735.     case _XE:
  1736.         return XE;
  1737.     case _SIN:
  1738.         return SIN;
  1739.     case _SHIN:
  1740.         return SHIN;
  1741.     case _SAD:
  1742.         return SAD;
  1743.     case _ZAD:
  1744.         return ZAD;
  1745.     case _AYN:
  1746.         return AYN;
  1747.     case _AYN_:
  1748.         return AYN_;
  1749.     case _GHAYN:
  1750.         return GHAYN;
  1751.     case _GHAYN_:
  1752.         return GHAYN_;
  1753.     case _FE:
  1754.         return FE;
  1755.     case _GHAF:
  1756.         return GHAF;
  1757.     case _KAF_H:
  1758.     case _KAF:
  1759.         return KAF;
  1760.     case _GAF:
  1761.         return GAF;
  1762.     case _LAM:
  1763.         return LAM;
  1764.     case _MIM:
  1765.         return MIM;
  1766.     case _NOON:
  1767.         return NOON;
  1768.     case _YE:
  1769.         return YE_;
  1770.     case YE_:
  1771.         return YE;
  1772.     case _YEE:
  1773.         return YEE_;
  1774.     case YEE_:
  1775.         return YEE;
  1776.     case TEE:
  1777.         return TEE_;
  1778.     case _IE:
  1779.         return IE_;
  1780.     case IE_:
  1781.         return IE;
  1782.     case _HE:
  1783.     case _HE_:
  1784.         return F_HE;
  1785.     }
  1786.     return c;
  1787. }
  1788.  
  1789. /*
  1790. ** Convert the Farsi 3342 standard into Farsi VIM.
  1791. */
  1792.     void
  1793. conv_to_pvim()
  1794. {
  1795. char_u *ptr;
  1796. int lnum, llen, i;
  1797.  
  1798.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1799.     {
  1800.     ptr = ml_get((linenr_t)lnum);
  1801.  
  1802.     llen = STRLEN(ptr);
  1803.  
  1804.     for ( i = 0; i < llen-1; i++)
  1805.     {
  1806.         if (canF_Ljoin(ptr[i]) && canF_Rjoin(ptr[i+1]))
  1807.         {
  1808.         ptr[i] = toF_leading(ptr[i]);
  1809.         ++i;
  1810.  
  1811.         while(canF_Rjoin(ptr[i]) && (i < llen))
  1812.         {
  1813.             ptr[i] = toF_Rjoin(ptr[i]);
  1814.             if (F_isterm(ptr[i]) || !F_isalpha(ptr[i]))
  1815.             break;
  1816.             ++i;
  1817.         }
  1818.         if (!F_isalpha(ptr[i]) || !canF_Rjoin(ptr[i]))
  1819.             ptr[i-1] = toF_ending(ptr[i-1]);
  1820.         }
  1821.         else
  1822.         ptr[i] = toF_TyA(ptr[i]);
  1823.     }
  1824.     }
  1825.  
  1826.     /*
  1827.     ** Following lines contains Farsi encoded character.
  1828.     */
  1829.  
  1830.     do_cmdline((char_u *)"%s/‚™/š/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1831.     do_cmdline((char_u *)"%s/™/øÜ/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1832.  
  1833.     update_screen(CLEAR);
  1834.     MSG_ATTR(farsi_text_1, highlight_attr[HLF_S]);
  1835. }
  1836.  
  1837. /*
  1838. ** Convert the Farsi VIM into Farsi 3342 standad.
  1839. */
  1840.     void
  1841. conv_to_pstd()
  1842. {
  1843. char_u *ptr;
  1844. int lnum, llen, i;
  1845.  
  1846.     /*
  1847.     ** Following line contains Farsi encoded character.
  1848.     */
  1849.  
  1850.     do_cmdline((char_u *)"%s/š/‚™/g", NULL, NULL, DOCMD_NOWAIT | DOCMD_VERBOSE);
  1851.  
  1852.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1853.     {
  1854.     ptr = ml_get((linenr_t)lnum);
  1855.  
  1856.     llen = STRLEN(ptr);
  1857.  
  1858.     for ( i = 0; i < llen; i++)
  1859.     {
  1860.         ptr[i] = toF_TyA(ptr[i]);
  1861.  
  1862.     }
  1863.     }
  1864.  
  1865.     update_screen(CLEAR);
  1866.     MSG_ATTR(farsi_text_2, highlight_attr[HLF_S]);
  1867. }
  1868.  
  1869. /*
  1870.  * left-right swap the characters in buf[len].
  1871.  */
  1872.     static void
  1873. lrswapbuf(buf, len)
  1874.     char_u    *buf;
  1875.     int        len;
  1876. {
  1877.     char_u    *s, *e;
  1878.     int        c;
  1879.  
  1880.     s = buf;
  1881.     e = buf + len - 1;
  1882.  
  1883.     while (e > s)
  1884.     {
  1885.     c = *s;
  1886.     *s = *e;
  1887.     *e = c;
  1888.     ++s;
  1889.     --e;
  1890.     }
  1891. }
  1892.  
  1893. /*
  1894.  * swap all the characters in reverse direction
  1895.  */
  1896.     char_u *
  1897. lrswap(ibuf)
  1898.     char_u    *ibuf;
  1899. {
  1900.     if (ibuf != NULL && *ibuf != NUL)
  1901.     lrswapbuf(ibuf, (int)STRLEN(ibuf));
  1902.     return ibuf;
  1903. }
  1904.  
  1905. /*
  1906.  * swap all the Farsi characters in reverse direction
  1907.  */
  1908.     char_u *
  1909. lrFswap(cmdbuf, len)
  1910.     char_u    *cmdbuf;
  1911.     int        len;
  1912. {
  1913.     int        i, cnt;
  1914.  
  1915.     if (cmdbuf == NULL)
  1916.     return cmdbuf;
  1917.  
  1918.     if (len == 0 && (len = STRLEN(cmdbuf)) == 0)
  1919.     return cmdbuf;
  1920.  
  1921.     for (i = 0; i < len; i++)
  1922.     {
  1923.     for (cnt = 0; i + cnt < len
  1924.             && (F_isalpha(cmdbuf[i + cnt])
  1925.                 || F_isdigit(cmdbuf[i + cnt])
  1926.                 || cmdbuf[i + cnt] == ' '); ++cnt)
  1927.         ;
  1928.  
  1929.     lrswapbuf(cmdbuf + i, cnt);
  1930.     i += cnt;
  1931.     }
  1932.     return cmdbuf;
  1933. }
  1934.  
  1935. /*
  1936.  * Reverse the characters in the seach path and substitude section accordingly
  1937.  */
  1938.     char_u *
  1939. lrF_sub(ibuf)
  1940.     char_u    *ibuf;
  1941. {
  1942.     char_u    *p, *ep;
  1943.     int        i, cnt;
  1944.  
  1945.     p = ibuf;
  1946.  
  1947.     /* Find the boundry of the search path */
  1948.     while ((p = vim_strchr(++p, '/')) && p[-1] == '\\')
  1949.     ;
  1950.  
  1951.     if (p == NULL)
  1952.     return ibuf;
  1953.  
  1954.     /* Reverse the Farsi characters in the search path. */
  1955.     lrFswap(ibuf, (int)(p-ibuf));
  1956.  
  1957.     /* Now find the boundry of the substitute section */
  1958.     if ((ep = (char_u *)strrchr((char *)++p, '/')))
  1959.     cnt = ep - p;
  1960.     else
  1961.     cnt = STRLEN(p);
  1962.  
  1963.     /* Reverse the characters in the substitute section and take care of '\' */
  1964.     for (i = 0; i < cnt-1; i++)
  1965.     if (p[i] == '\\')
  1966.     {
  1967.         p[i] = p[i+1] ;
  1968.         p[++i] = '\\';
  1969.     }
  1970.  
  1971.     lrswapbuf(p, cnt);
  1972.  
  1973.     return ibuf;
  1974. }
  1975.  
  1976. /*
  1977.  * Map Farsi keyboard when in cmd_fkmap mode.
  1978.  */
  1979.     int
  1980. cmdl_fkmap(c)
  1981.     int c;
  1982. {
  1983. int    tempc;
  1984.  
  1985.     switch (c)
  1986.     {
  1987.     case '0':
  1988.     case '1':
  1989.     case '2':
  1990.     case '3':
  1991.     case '4':
  1992.     case '5':
  1993.     case '6':
  1994.     case '7':
  1995.     case '8':
  1996.     case '9':
  1997.     case '`':
  1998.     case ' ':
  1999.     case '.':
  2000.     case '!':
  2001.     case '"':
  2002.     case '$':
  2003.     case '%':
  2004.     case '^':
  2005.     case '&':
  2006.     case '/':
  2007.     case '(':
  2008.     case ')':
  2009.     case '=':
  2010.     case '\\':
  2011.     case '?':
  2012.     case '+':
  2013.     case '-':
  2014.     case '_':
  2015.     case '*':
  2016.     case ':':
  2017.     case '#':
  2018.     case '~':
  2019.     case '@':
  2020.     case '<':
  2021.     case '>':
  2022.     case '{':
  2023.     case '}':
  2024.     case '|':
  2025.     case 'B':
  2026.     case 'E':
  2027.     case 'F':
  2028.     case 'H':
  2029.     case 'I':
  2030.     case 'K':
  2031.     case 'L':
  2032.     case 'M':
  2033.     case 'O':
  2034.     case 'P':
  2035.     case 'Q':
  2036.     case 'R':
  2037.     case 'T':
  2038.     case 'U':
  2039.     case 'W':
  2040.     case 'Y':
  2041.     case  NL:
  2042.     case  TAB:
  2043.  
  2044.            switch ((tempc = cmd_gchar(AT_CURSOR)))
  2045.            {
  2046.         case _BE:
  2047.         case _PE:
  2048.         case _TE:
  2049.         case _SE:
  2050.         case _JIM:
  2051.         case _CHE:
  2052.         case _HE_J:
  2053.         case _XE:
  2054.         case _SIN:
  2055.         case _SHIN:
  2056.         case _SAD:
  2057.         case _ZAD:
  2058.         case _AYN:
  2059.         case _GHAYN:
  2060.         case _FE:
  2061.         case _GHAF:
  2062.         case _KAF:
  2063.         case _GAF:
  2064.         case _LAM:
  2065.         case _MIM:
  2066.         case _NOON:
  2067.         case _HE:
  2068.         case _HE_:
  2069.             cmd_pchar(toF_TyA(tempc), AT_CURSOR);
  2070.         break;
  2071.         case _AYN_:
  2072.             cmd_pchar(AYN_, AT_CURSOR);
  2073.         break;
  2074.         case _GHAYN_:
  2075.             cmd_pchar(GHAYN_, AT_CURSOR);
  2076.         break;
  2077.         case _IE:
  2078.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2079.                 cmd_pchar(IE_, AT_CURSOR);
  2080.         else
  2081.                 cmd_pchar(IE, AT_CURSOR);
  2082.         break;
  2083.         case _YEE:
  2084.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2085.                 cmd_pchar(YEE_, AT_CURSOR);
  2086.             else
  2087.                 cmd_pchar(YEE, AT_CURSOR);
  2088.         break;
  2089.         case _YE:
  2090.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR+1))
  2091.                 cmd_pchar(YE_, AT_CURSOR);
  2092.             else
  2093.                 cmd_pchar(YE, AT_CURSOR);
  2094.         }
  2095.  
  2096.         switch (c)
  2097.         {
  2098.         case '0':   return FARSI_0;
  2099.         case '1':   return FARSI_1;
  2100.         case '2':   return FARSI_2;
  2101.         case '3':   return FARSI_3;
  2102.         case '4':   return FARSI_4;
  2103.         case '5':   return FARSI_5;
  2104.         case '6':   return FARSI_6;
  2105.         case '7':   return FARSI_7;
  2106.         case '8':   return FARSI_8;
  2107.         case '9':   return FARSI_9;
  2108.         case 'B':   return F_PSP;
  2109.         case 'E':   return JAZR_N;
  2110.         case 'F':   return ALEF_D_H;
  2111.         case 'H':   return ALEF_A;
  2112.         case 'I':   return TASH;
  2113.         case 'K':   return F_LQUOT;
  2114.         case 'L':   return F_RQUOT;
  2115.         case 'M':   return HAMZE;
  2116.         case 'O':   return '[';
  2117.         case 'P':   return ']';
  2118.         case 'Q':   return OO;
  2119.         case 'R':   return MAD_N;
  2120.         case 'T':   return OW;
  2121.         case 'U':   return MAD;
  2122.         case 'W':   return OW_OW;
  2123.         case 'Y':   return JAZR;
  2124.         case '`':   return F_PCN;
  2125.         case '!':   return F_EXCL;
  2126.         case '@':   return F_COMMA;
  2127.         case '#':   return F_DIVIDE;
  2128.         case '$':   return F_CURRENCY;
  2129.         case '%':   return F_PERCENT;
  2130.         case '^':   return F_MUL;
  2131.         case '&':   return F_BCOMMA;
  2132.         case '*':   return F_STAR;
  2133.         case '(':   return F_LPARENT;
  2134.         case ')':   return F_RPARENT;
  2135.         case '-':   return F_MINUS;
  2136.         case '_':   return F_UNDERLINE;
  2137.         case '=':   return F_EQUALS;
  2138.         case '+':   return F_PLUS;
  2139.         case '\\':  return F_BSLASH;
  2140.         case '|':   return F_PIPE;
  2141.         case ':':   return F_DCOLON;
  2142.         case '"':   return F_SEMICOLON;
  2143.         case '.':   return F_PERIOD;
  2144.         case '/':   return F_SLASH;
  2145.         case '<':   return F_LESS;
  2146.         case '>':   return F_GREATER;
  2147.         case '?':   return F_QUESTION;
  2148.         case ' ':   return F_BLANK;
  2149.         }
  2150.  
  2151.         break;
  2152.  
  2153.     case 'a':   return _SHIN;
  2154.     case 'A':   return WAW_H;
  2155.     case 'b':   return ZAL;
  2156.     case 'c':   return ZE;
  2157.     case 'C':   return JE;
  2158.     case 'd':   return _YE;
  2159.     case 'D':   return _YEE;
  2160.     case 'e':   return _SE;
  2161.     case 'f':   return _BE;
  2162.     case 'g':   return _LAM;
  2163.     case 'G':
  2164.             if (cmd_gchar(AT_CURSOR) == _LAM )
  2165.         {
  2166.             cmd_pchar(LAM, AT_CURSOR);
  2167.                 return ALEF_U_H;
  2168.         }
  2169.  
  2170.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2171.             return ALEF_U_H_;
  2172.         else
  2173.             return ALEF_U_H;
  2174.     case 'h':
  2175.             if (cmd_gchar(AT_CURSOR) == _LAM )
  2176.         {
  2177.             cmd_pchar(LA, AT_CURSOR);
  2178.             redrawcmdline();
  2179.             return K_IGNORE;
  2180.         }
  2181.  
  2182.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2183.             return ALEF_;
  2184.         else
  2185.             return ALEF;
  2186.     case 'i':
  2187.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2188.             return _HE_;
  2189.         else
  2190.             return _HE;
  2191.     case 'j':   return _TE;
  2192.     case 'J':
  2193.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2194.             return TEE_;
  2195.         else
  2196.             return TEE;
  2197.     case 'k':   return _NOON;
  2198.     case 'l':   return _MIM;
  2199.     case 'm':   return _PE;
  2200.     case 'n':
  2201.     case 'N':   return DAL;
  2202.     case 'o':   return _XE;
  2203.     case 'p':   return _HE_J;
  2204.     case 'q':   return _ZAD;
  2205.     case 'r':   return _GHAF;
  2206.     case 's':   return _SIN;
  2207.     case 'S':   return _IE;
  2208.     case 't':   return _FE;
  2209.     case 'u':
  2210.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2211.             return _AYN_;
  2212.         else
  2213.             return _AYN;
  2214.     case 'v':
  2215.     case 'V':   return RE;
  2216.     case 'w':   return _SAD;
  2217.     case 'x':
  2218.     case 'X':   return _TA;
  2219.     case 'y':
  2220.         if (F_is_TyB_TyC_TyD(SRC_CMD, AT_CURSOR))
  2221.             return _GHAYN_;
  2222.         else
  2223.             return _GHAYN;
  2224.     case 'z':
  2225.     case 'Z':   return _ZA;
  2226.     case ';':   return _KAF;
  2227.     case '\'':  return _GAF;
  2228.     case ',':   return WAW;
  2229.     case '[':   return _JIM;
  2230.     case ']':   return _CHE;
  2231.     }
  2232.  
  2233.     return c;
  2234. }
  2235.  
  2236. /*
  2237.  * F_isalpha returns TRUE if 'c' is a Farsi alphabet
  2238.  */
  2239.     int
  2240. F_isalpha(c)
  2241.     int    c;
  2242. {
  2243.     return (( c >= TEE_ && c <= _YE) ||
  2244.     ( c >= ALEF_A && c <= YE) ||
  2245.     ( c >= _IE && c <= YE_));
  2246. }
  2247.  
  2248. /*
  2249.  * F_isdigit returns TRUE if 'c' is a Farsi digit
  2250.  */
  2251.     int
  2252. F_isdigit(c)
  2253.     int        c;
  2254. {
  2255.     return (( c >= FARSI_0 && c <= FARSI_9 ));
  2256. }
  2257.  
  2258. /*
  2259.  * F_ischar returns TRUE if 'c' is a Farsi character.
  2260.  */
  2261.     int
  2262. F_ischar(c)
  2263.     int        c;
  2264. {
  2265.     return (( c >= TEE_ && c <= YE_));
  2266. }
  2267.  
  2268.     void
  2269. farsi_fkey(c)
  2270.     int        c;
  2271. {
  2272.     if (c == K_F8)
  2273.     {
  2274.     if (p_altkeymap)
  2275.     {
  2276.         if (curwin->w_p_pers & W_R_L)
  2277.         {
  2278.         p_fkmap=0;
  2279.         do_cmdline((char_u *)"set norl", NULL, NULL, DOCMD_NOWAIT);
  2280.         MSG("");
  2281.         }
  2282.         else
  2283.         {
  2284.         p_fkmap=1;
  2285.         do_cmdline((char_u *)"set rl", NULL, NULL, DOCMD_NOWAIT);
  2286.         MSG("");
  2287.         }
  2288.  
  2289.         curwin->w_p_pers = curwin->w_p_pers ^ W_R_L;
  2290.     }
  2291.     }
  2292.  
  2293.     if (c == K_F9)
  2294.     {
  2295.     if (p_altkeymap && curwin->w_p_rl)
  2296.     {
  2297.         curwin->w_p_pers = curwin->w_p_pers ^ W_CONV;
  2298.         if (curwin->w_p_pers & W_CONV)
  2299.         conv_to_pvim();
  2300.         else
  2301.         conv_to_pstd();
  2302.     }
  2303.     }
  2304. }
  2305.